﻿using System;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;

namespace Microsoft.VisualStudio.NetworkEmulation
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private const string PROFILE_TAG = "PROFILE";

        private NotifyIcon m_notifyIcon;
        private ContextMenu m_notifyMenu = new ContextMenu();

        private MenuItem m_miStartEmulation;
        private MenuItem m_miStopEmulation;

        public MainWindow()
        {
            InitializeComponent();

            System.Windows.Controls.ContextMenu menu = new System.Windows.Controls.ContextMenu();
            m_notifyMenu.MenuItems.Add(m_miStartEmulation = 
                new MenuItem("Start Emulation", new EventHandler(mi_StartEmulation)));
            m_notifyMenu.MenuItems.Add(m_miStopEmulation = 
                new MenuItem("Stop Emulation", new EventHandler(mi_StopEmulation)));
            m_notifyMenu.MenuItems.Add(new MenuItem("-"));

            // Add to the system tray.
            m_notifyIcon = new System.Windows.Forms.NotifyIcon();
            m_notifyIcon.Icon = System.Drawing.Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
            m_notifyIcon.Visible = false;
            m_notifyIcon.ContextMenu = m_notifyMenu;
            m_notifyIcon.DoubleClick +=
                delegate(object sender, EventArgs args)
                {
                    this.Show();
                    this.WindowState = WindowState.Normal;
                };
        }

        protected override void OnStateChanged(EventArgs e)
        {
            m_notifyIcon.Visible = (this.WindowState == System.Windows.WindowState.Minimized);

            if (WindowState == WindowState.Minimized)
            {
                this.Hide();
            }

            base.OnStateChanged(e);
        }

        private void Initialize()
        {
            NetworkEmulationState.GetInstance().DriverStateChanged += new EventHandler(MainWindow_DriverStateChanged);

            // By this time, we would have missed the initial state change event, 
            // so initialize it now.
            MainWindow_DriverStateChanged(this, new EventArgs());

            // Load the network templates from the network template dir.
            String[] items = Directory.GetFiles("Profiles", "*.network");
            if (null != items)
            {
                // Add all the profile names to the combobox and context menu
                foreach (string item in items)
                {
                    string name = System.IO.Path.GetFileNameWithoutExtension(item);
                    MenuItem mi = new MenuItem(name, new EventHandler(mi_Click));
                    mi.Name = name;
                    mi.Tag = PROFILE_TAG;
                    m_notifyMenu.MenuItems.Add(mi);
                    m_networkProfiles.Items.Add(name);
                }
            }

            m_notifyMenu.MenuItems.Add(new MenuItem("-"));
            m_notifyMenu.MenuItems.Add(new MenuItem("E&xit", new EventHandler(mi_Exit)));

            // Try to set the default profile to LAN
            SetSelectedProfile("LAN");
            
            if (-1 == m_networkProfiles.SelectedIndex && m_networkProfiles.Items.Count > 0)
            {
                // Set the default profile to the first one in the list
                m_networkProfiles.SelectedIndex = 0;
            }
        }

        private void SetProfilesEnabledState(bool enabled)
        {
            foreach (MenuItem item in m_notifyMenu.MenuItems)
            {
                if (PROFILE_TAG.Equals(item.Tag))
                {
                    item.Enabled = enabled;
                }
            }
        }

        private void SetSelectedProfile(string profileName)
        {
            // Clear the previously selected profiles
            foreach (MenuItem item in m_notifyMenu.MenuItems)
            {
                item.Checked = false;
            }

            MenuItem[] mi = m_notifyMenu.MenuItems.Find(profileName, false);
            if (mi.Length > 0)
            {
                mi[0].Checked = true;
            }

            m_networkProfiles.SelectedValue = profileName;
        }

        #region EventHandlers

        private void mi_Click(object sender, EventArgs e)
        {
            MenuItem mi = (MenuItem)sender;
            if (null != mi)
            {
                SetSelectedProfile(mi.Text);
            }
        }

        private void mi_Exit(object sender, EventArgs e)
        {
            this.Close();
        }

        private void mi_StartEmulation(object sender, EventArgs e)
        {
            m_startCommand.Execute(m_startEmulation.CommandParameter);
        }

        private void mi_StopEmulation(object sender, EventArgs e)
        {
            m_stopCommand.Execute(null);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Initialize();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // We don't want to create a new instance if the existing one was already shut down.
            if (null != NetworkEmulationState.PeekInstance())
            {
                NetworkEmulationState.GetInstance().DriverStateChanged -= new EventHandler(MainWindow_DriverStateChanged);
            }
            m_notifyIcon.Visible = false;
        }

        private void m_networkProfiles_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            m_startEmulation.CommandParameter = System.IO.Path.Combine("Profiles", m_networkProfiles.SelectedItem + ".Network");
            SetSelectedProfile((string) m_networkProfiles.SelectedItem);
        }

        protected void MainWindow_DriverStateChanged(object sender, EventArgs e)
        {
            m_miStartEmulation.Enabled = (NetworkEmulationState.GetInstance().DriverState.Equals(DriverState.Initialized));
            m_miStopEmulation.Enabled =  (NetworkEmulationState.GetInstance().DriverState.Equals(DriverState.Emulating));
            SetProfilesEnabledState(m_miStartEmulation.Enabled);
        }

        #endregion

        #region Network Emulation Commands

        private static ICommand m_startCommand = new NetworkEmulationStartCommand();
        private static ICommand m_stopCommand = new NetworkEmulationStopCommand();

        public static ICommand StartCommand
        {
            get { return MainWindow.m_startCommand; }
            set { MainWindow.m_startCommand = value; }
        }

        public static ICommand StopCommand
        {
            get { return MainWindow.m_stopCommand; }
            set { MainWindow.m_stopCommand = value; }
        }

        #endregion
    }
}

